//! # 代码生成命令
//!
//! 用于生成服务、模型、配置等代码

use crate::config::CliConfig;
use crate::error::{CliError, CliResult};
use crate::templates::TemplateEngine;
use crate::generate_helpers::*;
use clap::Args;
use colored::*;
use console::Emoji;
use std::collections::HashMap;
use std::path::Path;
use tokio::fs;
use tracing::info;

static GEAR: Emoji<'_, '_> = Emoji("⚙️ ", "");
static CHECK: Emoji<'_, '_> = Emoji("✅ ", "");
static SPARKLE: Emoji<'_, '_> = Emoji("✨ ", "");

/// 代码生成命令参数
#[derive(Args, Debug)]
pub struct GenerateArgs {
    /// 生成类型
    #[arg(value_enum)]
    pub generate_type: GenerateType,

    /// 生成目标名称
    pub name: String,

    /// 输出目录
    #[arg(short, long)]
    pub output: Option<String>,

    /// 是否覆盖已存在的文件
    #[arg(short, long)]
    pub force: bool,
}

/// 生成类型
#[derive(clap::ValueEnum, Debug, Clone)]
pub enum GenerateType {
    /// 生成服务
    Service,
    /// 生成模型
    Model,
    /// 生成配置
    Config,
    /// 生成客户端
    Client,
    /// 生成测试
    Test,
}

/// 执行代码生成命令
pub async fn execute(args: GenerateArgs, config: CliConfig) -> CliResult<()> {
    println!("{} {}生成 {:?}: {}", GEAR, "开始".bright_green().bold(), args.generate_type, args.name.bright_yellow());

    // 验证当前目录是否为 RustCloud 项目
    validate_rustcloud_project().await?;

    match args.generate_type {
        GenerateType::Service => generate_service(&args, &config).await,
        GenerateType::Model => generate_model(&args, &config).await,
        GenerateType::Config => generate_config(&args, &config).await,
        GenerateType::Client => generate_client(&args, &config).await,
        GenerateType::Test => generate_test(&args, &config).await,
    }?;

    println!("{} {}代码生成完成！", CHECK, "成功".bright_green().bold());
    Ok(())
}

async fn generate_service(args: &GenerateArgs, config: &CliConfig) -> CliResult<()> {
    info!("生成微服务: {}", args.name);

    let service_name = &args.name;
    let snake_case_name = to_snake_case(service_name);
    let output_dir = args.output.as_deref().unwrap_or("src/services");
    let service_dir = Path::new(output_dir).join(&snake_case_name);

    // 创建服务目录
    fs::create_dir_all(&service_dir).await?;

    // 初始化模板引擎
    let template_engine = TemplateEngine::new(config)?;

    // 准备模板变量
    let mut variables = HashMap::new();
    variables.insert("service_name".to_string(), serde_json::json!(service_name));
    variables.insert("snake_case_name".to_string(), serde_json::json!(snake_case_name));
    variables.insert("pascal_case_name".to_string(), serde_json::json!(to_pascal_case(service_name)));
    variables.insert("author".to_string(), serde_json::json!(config.global.author.name));
    variables.insert("email".to_string(), serde_json::json!(config.global.author.email));

    // 生成服务主文件
    generate_service_main(&service_dir, &variables).await?;
    
    // 生成服务处理器
    generate_service_handler(&service_dir, &variables).await?;
    
    // 生成服务模型
    generate_service_model(&service_dir, &variables).await?;
    
    // 生成服务错误处理
    generate_service_error(&service_dir, &variables).await?;
    
    // 生成服务测试
    generate_service_test(&service_dir, &variables).await?;

    // 更新 lib.rs 或 main.rs 添加模块声明
    update_module_declarations(&snake_case_name).await?;

    println!("{} {}服务生成完成: {}", SPARKLE, "成功".bright_green(), service_dir.display().to_string().bright_blue());
    Ok(())
}

async fn generate_model(args: &GenerateArgs, config: &CliConfig) -> CliResult<()> {
    info!("生成数据模型: {}", args.name);

    let model_name = &args.name;
    let snake_case_name = to_snake_case(model_name);
    let output_dir = args.output.as_deref().unwrap_or("src/models");
    let model_file = Path::new(output_dir).join(format!("{}.rs", snake_case_name));

    // 创建模型目录
    if let Some(parent) = model_file.parent() {
        fs::create_dir_all(parent).await?;
    }

    // 准备模板变量
    let mut variables = HashMap::new();
    variables.insert("model_name".to_string(), serde_json::json!(model_name));
    variables.insert("snake_case_name".to_string(), serde_json::json!(snake_case_name));
    variables.insert("pascal_case_name".to_string(), serde_json::json!(to_pascal_case(model_name)));
    variables.insert("author".to_string(), serde_json::json!(config.global.author.name));
    variables.insert("email".to_string(), serde_json::json!(config.global.author.email));

    // 生成模型文件
    generate_model_file(&model_file, &variables).await?;

    // 更新 models/mod.rs
    update_models_mod(&snake_case_name).await?;

    println!("{} {}模型生成完成: {}", SPARKLE, "成功".bright_green(), model_file.display().to_string().bright_blue());
    Ok(())
}

async fn generate_config(args: &GenerateArgs, config: &CliConfig) -> CliResult<()> {
    info!("生成配置文件: {}", args.name);

    let config_name = &args.name;
    let snake_case_name = to_snake_case(config_name);
    let output_dir = args.output.as_deref().unwrap_or("src/config");
    let config_file = Path::new(output_dir).join(format!("{}.rs", snake_case_name));

    // 创建配置目录
    if let Some(parent) = config_file.parent() {
        fs::create_dir_all(parent).await?;
    }

    // 准备模板变量
    let mut variables = HashMap::new();
    variables.insert("config_name".to_string(), serde_json::json!(config_name));
    variables.insert("snake_case_name".to_string(), serde_json::json!(snake_case_name));
    variables.insert("pascal_case_name".to_string(), serde_json::json!(to_pascal_case(config_name)));
    variables.insert("author".to_string(), serde_json::json!(config.global.author.name));
    variables.insert("email".to_string(), serde_json::json!(config.global.author.email));

    // 生成配置文件
    generate_config_file(&config_file, &variables).await?;

    // 更新 config/mod.rs
    update_config_mod(&snake_case_name).await?;

    println!("{} {}配置生成完成: {}", SPARKLE, "成功".bright_green(), config_file.display().to_string().bright_blue());
    Ok(())
}

async fn generate_client(args: &GenerateArgs, config: &CliConfig) -> CliResult<()> {
    info!("生成客户端代码: {}", args.name);

    let client_name = &args.name;
    let snake_case_name = to_snake_case(client_name);
    let output_dir = args.output.as_deref().unwrap_or("src/clients");
    let client_file = Path::new(output_dir).join(format!("{}.rs", snake_case_name));

    // 创建客户端目录
    if let Some(parent) = client_file.parent() {
        fs::create_dir_all(parent).await?;
    }

    // 准备模板变量
    let mut variables = HashMap::new();
    variables.insert("client_name".to_string(), serde_json::json!(client_name));
    variables.insert("snake_case_name".to_string(), serde_json::json!(snake_case_name));
    variables.insert("pascal_case_name".to_string(), serde_json::json!(to_pascal_case(client_name)));
    variables.insert("author".to_string(), serde_json::json!(config.global.author.name));
    variables.insert("email".to_string(), serde_json::json!(config.global.author.email));

    // 生成客户端文件
    generate_client_file(&client_file, &variables).await?;

    // 更新 clients/mod.rs
    update_clients_mod(&snake_case_name).await?;

    println!("{} {}客户端生成完成: {}", SPARKLE, "成功".bright_green(), client_file.display().to_string().bright_blue());
    Ok(())
}

async fn generate_test(args: &GenerateArgs, config: &CliConfig) -> CliResult<()> {
    info!("生成测试代码: {}", args.name);

    let test_name = &args.name;
    let snake_case_name = to_snake_case(test_name);
    let output_dir = args.output.as_deref().unwrap_or("tests");
    let test_file = Path::new(output_dir).join(format!("{}.rs", snake_case_name));

    // 创建测试目录
    if let Some(parent) = test_file.parent() {
        fs::create_dir_all(parent).await?;
    }

    // 准备模板变量
    let mut variables = HashMap::new();
    variables.insert("test_name".to_string(), serde_json::json!(test_name));
    variables.insert("snake_case_name".to_string(), serde_json::json!(snake_case_name));
    variables.insert("pascal_case_name".to_string(), serde_json::json!(to_pascal_case(test_name)));
    variables.insert("author".to_string(), serde_json::json!(config.global.author.name));
    variables.insert("email".to_string(), serde_json::json!(config.global.author.email));

    // 生成测试文件
    generate_test_file(&test_file, &variables).await?;

    println!("{} {}测试生成完成: {}", SPARKLE, "成功".bright_green(), test_file.display().to_string().bright_blue());
    Ok(())
}

// =============================================================================
// 辅助函数
// =============================================================================

/// 验证当前目录是否为 RustCloud 项目
async fn validate_rustcloud_project() -> CliResult<()> {
    let cargo_toml = Path::new("Cargo.toml");
    if !cargo_toml.exists() {
        return Err(CliError::validation("当前目录不是一个 Rust 项目（未找到 Cargo.toml）"));
    }

    let content = fs::read_to_string(cargo_toml).await?;
    if !content.contains("rustcloud") {
        return Err(CliError::validation("当前项目不是 RustCloud 项目（Cargo.toml 中未发现 rustcloud 依赖）"));
    }

    Ok(())
}

/// 转换为蛇形命名
fn to_snake_case(s: &str) -> String {
    s.replace(&['-', ' '][..], "_")
        .chars()
        .flat_map(|c| {
            if c.is_uppercase() {
                vec!['_', c.to_lowercase().next().unwrap()]
            } else {
                vec![c]
            }
        })
        .collect::<String>()
        .trim_start_matches('_')
        .to_string()
}

/// 转换为帕斯卡尔命名
fn to_pascal_case(s: &str) -> String {
    s.split(&['-', '_', ' '][..])
        .map(|word| {
            let mut chars = word.chars();
            match chars.next() {
                None => String::new(),
                Some(first) => first.to_uppercase().collect::<String>() + chars.as_str(),
            }
        })
        .collect()
}

// =============================================================================
// 服务生成实现
// =============================================================================

/// 生成服务主文件
async fn generate_service_main(
    service_dir: &Path,
    variables: &HashMap<String, serde_json::Value>,
) -> CliResult<()> {
    let template = r#"//! # {{pascal_case_name}} 服务
//!
//! 使用 RustCloud 框架实现的微服务
//!
//! Author: {{author}} <{{email}}>

use rustcloud::prelude::*;
use tracing::{info, error};
use std::sync::Arc;

mod handler;
mod model;
mod error;

use handler::{{pascal_case_name}}Handler;
pub use model::*;
pub use error::{{pascal_case_name}}Error;

/// {{pascal_case_name}} 服务
#[derive(Clone)]
pub struct {{pascal_case_name}}Service {
    handler: Arc<{{pascal_case_name}}Handler>,
}

impl {{pascal_case_name}}Service {
    /// 创建新的服务实例
    pub fn new() -> Self {
        Self {
            handler: Arc::new({{pascal_case_name}}Handler::new()),
        }
    }

    /// 启动服务
    pub async fn start(&self) -> Result<(), {{pascal_case_name}}Error> {
        info!("🚀 启动 {{pascal_case_name}} 服务");
        
        // TODO: 在这里添加服务启动逻辑
        
        Ok(())
    }

    /// 停止服务
    pub async fn stop(&self) -> Result<(), {{pascal_case_name}}Error> {
        info!("📴 停止 {{pascal_case_name}} 服务");
        
        // TODO: 在这里添加服务停止逻辑
        
        Ok(())
    }

    /// 获取服务处理器
    pub fn handler(&self) -> Arc<{{pascal_case_name}}Handler> {
        self.handler.clone()
    }
}

impl Default for {{pascal_case_name}}Service {
    fn default() -> Self {
        Self::new()
    }
}
"#;

    let handlebars = handlebars::Handlebars::new();
    let rendered = handlebars.render_template(template, variables)?;
    
    let main_file = service_dir.join("mod.rs");
    fs::write(main_file, rendered).await?;
    
    Ok(())
}

/// 生成服务处理器
async fn generate_service_handler(
    service_dir: &Path,
    variables: &HashMap<String, serde_json::Value>,
) -> CliResult<()> {
    let template = r#"//! # {{pascal_case_name}} 处理器
//!
//! 处理具体的业务逻辑

use crate::{{snake_case_name}}::{{pascal_case_name}}Error;
use rustcloud::prelude::*;
use tracing::{info, warn, error};
use std::collections::HashMap;

/// {{pascal_case_name}} 处理器
#[derive(Debug, Clone)]
pub struct {{pascal_case_name}}Handler {
    // TODO: 添加必要的依赖和配置
}

impl {{pascal_case_name}}Handler {
    /// 创建新的处理器
    pub fn new() -> Self {
        Self {
            // TODO: 初始化必要的依赖
        }
    }

    /// 处理请求示例
    pub async fn handle_request(&self, _request: HashMap<String, String>) -> Result<String, {{pascal_case_name}}Error> {
        info!("处理 {{pascal_case_name}} 请求");
        
        // TODO: 实现具体的业务逻辑
        
        Ok("请求处理成功".to_string())
    }

    /// 创建资源示例
    pub async fn create(&self, _data: HashMap<String, String>) -> Result<String, {{pascal_case_name}}Error> {
        info!("创建 {{pascal_case_name}} 资源");
        
        // TODO: 实现创建逻辑
        
        Ok("create_id".to_string())
    }

    /// 查询资源示例
    pub async fn get(&self, id: &str) -> Result<Option<HashMap<String, String>>, {{pascal_case_name}}Error> {
        info!("查询 {{pascal_case_name}} 资源: {}", id);
        
        // TODO: 实现查询逻辑
        
        Ok(None)
    }

    /// 更新资源示例
    pub async fn update(&self, id: &str, _data: HashMap<String, String>) -> Result<(), {{pascal_case_name}}Error> {
        info!("更新 {{pascal_case_name}} 资源: {}", id);
        
        // TODO: 实现更新逻辑
        
        Ok(())
    }

    /// 删除资源示例
    pub async fn delete(&self, id: &str) -> Result<(), {{pascal_case_name}}Error> {
        info!("删除 {{pascal_case_name}} 资源: {}", id);
        
        // TODO: 实现删除逻辑
        
        Ok(())
    }
}

impl Default for {{pascal_case_name}}Handler {
    fn default() -> Self {
        Self::new()
    }
}
"#;

    let handlebars = handlebars::Handlebars::new();
    let rendered = handlebars.render_template(template, variables)?;
    
    let handler_file = service_dir.join("handler.rs");
    fs::write(handler_file, rendered).await?;
    
    Ok(())
}

/// 生成服务模型
async fn generate_service_model(
    service_dir: &Path,
    variables: &HashMap<String, serde_json::Value>,
) -> CliResult<()> {
    let template = r#"//! # {{pascal_case_name}} 数据模型
//!
//! 定义服务相关的数据结构

use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};
use uuid::Uuid;

/// {{pascal_case_name}} 数据模型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct {{pascal_case_name}} {
    /// 唯一标识符
    pub id: Uuid,
    
    /// 名称
    pub name: String,
    
    /// 描述
    pub description: Option<String>,
    
    /// 创建时间
    pub created_at: DateTime<Utc>,
    
    /// 更新时间
    pub updated_at: DateTime<Utc>,
    
    // TODO: 添加其他必要的字段
}

/// {{pascal_case_name}} 创建请求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Create{{pascal_case_name}}Request {
    /// 名称
    pub name: String,
    
    /// 描述
    pub description: Option<String>,
    
    // TODO: 添加其他必要的字段
}

/// {{pascal_case_name}} 更新请求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Update{{pascal_case_name}}Request {
    /// 名称
    pub name: Option<String>,
    
    /// 描述
    pub description: Option<String>,
    
    // TODO: 添加其他必要的字段
}

/// {{pascal_case_name}} 响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct {{pascal_case_name}}Response {
    /// {{pascal_case_name}} 数据
    pub data: {{pascal_case_name}},
    
    /// 消息
    pub message: Option<String>,
}

/// {{pascal_case_name}} 列表响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct {{pascal_case_name}}ListResponse {
    /// {{pascal_case_name}} 列表
    pub data: Vec<{{pascal_case_name}}>,
    
    /// 总数
    pub total: usize,
    
    /// 当前页
    pub page: usize,
    
    /// 每页大小
    pub page_size: usize,
}

impl {{pascal_case_name}} {
    /// 创建新的 {{pascal_case_name}}
    pub fn new(name: String, description: Option<String>) -> Self {
        let now = Utc::now();
        Self {
            id: Uuid::new_v4(),
            name,
            description,
            created_at: now,
            updated_at: now,
        }
    }
    
    /// 更新 {{pascal_case_name}}
    pub fn update(&mut self, request: Update{{pascal_case_name}}Request) {
        if let Some(name) = request.name {
            self.name = name;
        }
        if let Some(description) = request.description {
            self.description = Some(description);
        }
        self.updated_at = Utc::now();
    }
}

impl From<Create{{pascal_case_name}}Request> for {{pascal_case_name}} {
    fn from(request: Create{{pascal_case_name}}Request) -> Self {
        Self::new(request.name, request.description)
    }
}
"#;

    let handlebars = handlebars::Handlebars::new();
    let rendered = handlebars.render_template(template, variables)?;
    
    let model_file = service_dir.join("model.rs");
    fs::write(model_file, rendered).await?;
    
    Ok(())
}

/// 生成服务错误处理
async fn generate_service_error(
    service_dir: &Path,
    variables: &HashMap<String, serde_json::Value>,
) -> CliResult<()> {
    let template = r#"//! # {{pascal_case_name}} 错误定义
//!
//! 定义服务相关的错误类型

use thiserror::Error;
use serde::{Serialize, Deserialize};
use std::fmt;

/// {{pascal_case_name}} 服务错误
#[derive(Error, Debug, Clone, Serialize, Deserialize)]
pub enum {{pascal_case_name}}Error {
    /// 验证错误
    #[error("验证错误: {message}")]
    Validation { message: String },

    /// 资源未找到
    #[error("资源未找到: {resource} ID: {id}")]
    NotFound { resource: String, id: String },

    /// 数据库错误
    #[error("数据库错误: {message}")]
    Database { message: String },

    /// 网络错误
    #[error("网络错误: {message}")]
    Network { message: String },

    /// 权限错误
    #[error("权限不足: {message}")]
    Permission { message: String },

    /// 内部错误
    #[error("内部错误: {message}")]
    Internal { message: String },

    /// 配置错误
    #[error("配置错误: {message}")]
    Config { message: String },

    /// 外部服务错误
    #[error("外部服务错误: {service}: {message}")]
    ExternalService { service: String, message: String },
}

impl {{pascal_case_name}}Error {
    /// 创建验证错误
    pub fn validation(message: impl Into<String>) -> Self {
        Self::Validation {
            message: message.into(),
        }
    }

    /// 创建资源未找到错误
    pub fn not_found(resource: impl Into<String>, id: impl Into<String>) -> Self {
        Self::NotFound {
            resource: resource.into(),
            id: id.into(),
        }
    }

    /// 创建数据库错误
    pub fn database(message: impl Into<String>) -> Self {
        Self::Database {
            message: message.into(),
        }
    }

    /// 创建网络错误
    pub fn network(message: impl Into<String>) -> Self {
        Self::Network {
            message: message.into(),
        }
    }

    /// 创建权限错误
    pub fn permission(message: impl Into<String>) -> Self {
        Self::Permission {
            message: message.into(),
        }
    }

    /// 创建内部错误
    pub fn internal(message: impl Into<String>) -> Self {
        Self::Internal {
            message: message.into(),
        }
    }

    /// 创建配置错误
    pub fn config(message: impl Into<String>) -> Self {
        Self::Config {
            message: message.into(),
        }
    }

    /// 创建外部服务错误
    pub fn external_service(service: impl Into<String>, message: impl Into<String>) -> Self {
        Self::ExternalService {
            service: service.into(),
            message: message.into(),
        }
    }

    /// 获取错误代码
    pub fn code(&self) -> &'static str {
        match self {
            Self::Validation { .. } => "VALIDATION_ERROR",
            Self::NotFound { .. } => "NOT_FOUND",
            Self::Database { .. } => "DATABASE_ERROR",
            Self::Network { .. } => "NETWORK_ERROR",
            Self::Permission { .. } => "PERMISSION_DENIED",
            Self::Internal { .. } => "INTERNAL_ERROR",
            Self::Config { .. } => "CONFIG_ERROR",
            Self::ExternalService { .. } => "EXTERNAL_SERVICE_ERROR",
        }
    }

    /// 检查是否为可重试的错误
    pub fn is_retryable(&self) -> bool {
        matches!(self, Self::Network { .. } | Self::ExternalService { .. })
    }
}

/// 错误响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ErrorResponse {
    /// 错误代码
    pub code: String,
    /// 错误消息
    pub message: String,
    /// 详细信息
    pub details: Option<serde_json::Value>,
}

impl From<{{pascal_case_name}}Error> for ErrorResponse {
    fn from(error: {{pascal_case_name}}Error) -> Self {
        Self {
            code: error.code().to_string(),
            message: error.to_string(),
            details: None,
        }
    }
}
"#;

    let handlebars = handlebars::Handlebars::new();
    let rendered = handlebars.render_template(template, variables)?;
    
    let error_file = service_dir.join("error.rs");
    fs::write(error_file, rendered).await?;
    
    Ok(())
}